package com.ctshk.rpc.workflow.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.mail.core.MailTemplate;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.system.service.ISystemMessageService;
import com.ctshk.rpc.workflow.dto.*;
import com.ctshk.rpc.workflow.entity.*;
import com.ctshk.rpc.workflow.enums.ApproverType;
import com.ctshk.rpc.workflow.mapper.*;
import com.ctshk.rpc.workflow.req.ApprovalReq;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.MessagingException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * <p>
 * 审批 服务实现类
 * </p>
 *
 * @author 谢诗宏
 * @since 2021-01-25
 */
@Slf4j
@DubboService
public class SysApprovalServiceImpl extends ServiceImpl<SysApprovalMapper, SysApproval> implements ISysApprovalService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private SysApprovalMapper approvalMapper;
    @Autowired
    private SysApprovalMemberMapper memberMapper;
    @Autowired
    private SysApprovalConditionMapper conditionMapper;
    @Autowired
    private SysApprovalStepMapper stepMapper;
    @Autowired
    private SysApprovalProcessMapper processMapper;

    @Autowired
    private SysApprovalSettingMapper settingMapper;
    @Autowired
    private SysApprovalSettingMemberMapper settingMemberMapper;
    @Autowired
    private SysApprovalSettingConditionMapper settingConditionMapper;
    @Autowired
    private SysApprovalSettingSponsorMapper settingSponsorMapper;
    @Autowired
    private SysApprovalSettingStepMapper settingStepMapper;

    @DubboReference
    private ISysUserService sysUserService;
    @DubboReference
    private ISysDepartmentService sysDepartmentService;
    @DubboReference
    private ISystemMessageService systemMessageService;
    @Autowired
    private MailTemplate mailTemplate;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<ApprovalStartDTO> start(long businessTypeId, long approvalTypeId, long businessId, long userId, BigDecimal amount, String extendParams) {
        UserDTO userDTO = sysUserService.queryCacheUser(userId);
        List<Long> deptIds = new ArrayList<>();
        deptIds.add(userId);
        deptIds.addAll(sysDepartmentService.queryIdsByUserId(userId));
        SysApprovalSetting setting = settingMapper.getSettingByType(businessTypeId, approvalTypeId, deptIds);
        if (setting == null) {
            log.error("【审批-开始审批流】找不到审批配置，请在审批配置设置");
            return Result.failed(SystemError.WORKFLOW_APPROVAL_7001);
        }

        AtomicLong currentStepId = new AtomicLong(0L);
        AtomicLong nextStepId = new AtomicLong(0L);

        SysApproval sysApproval = new SysApproval();
        Long approvalId = SnowflakeIdWorker.nextId();
        sysApproval.setId(approvalId);
        sysApproval.setStatus(ApprovalStatus.REVIEWING.getCode());
//        sysApproval.setApprovalNumber(setting.getSysCode());
        sysApproval.setApprovalNumber(generatorApprovalNumber(userDTO));
        sysApproval.setSettingId(setting.getId());
        sysApproval.setSponsorId(userId);
        sysApproval.setSponsorName(userDTO.getFullName());
        sysApproval.setDepartmentId(userDTO.getDeptId());
        sysApproval.setDepartmentName(userDTO.getDept());
        sysApproval.setBusinessType(businessTypeId);
        sysApproval.setBusinessId(businessId);
        sysApproval.setAmount(amount);
        sysApproval.setExtendParams(extendParams);
        sysApproval.setCreateId(userId);
        sysApproval.setGmtCreate(LocalDateTime.now());
        sysApproval.setGmtModified(null);

        /**
         * 获取步骤数组 遍历插入业务审批相关表中 start
         */
        QueryWrapper<SysApprovalSettingStep> qw = new QueryWrapper<>();
        qw.lambda().eq(SysApprovalSettingStep::getSettingId, setting.getId())
                .eq(SysApprovalSettingStep::getIsDeleted, 0)
                .orderByAsc(SysApprovalSettingStep::getStep);//修改后加了一个根据步骤升序排列
        List<SysApprovalSettingStep> settingSteps = settingStepMapper.selectList(qw);
        Optional.ofNullable(settingSteps).orElse(new ArrayList<>()).forEach(settingStep -> {
            // 新增业务审批步骤数据
            SysApprovalStep sysApprovalStep = EntityUtil.copy(settingStep, SysApprovalStep.class);
            Long stepId = SnowflakeIdWorker.nextId();
            if (sysApprovalStep.getStep() == 1) {
                sysApproval.setCurrentStepId(stepId);
            } else if (sysApprovalStep.getStep() == 2) {
                sysApproval.setNextStepId(stepId);
            }

            sysApprovalStep.setId(stepId);
            sysApprovalStep.setApprovalId(approvalId);
            sysApprovalStep.setCreateId(userId);
            sysApprovalStep.setGmtCreate(LocalDateTime.now());
            sysApprovalStep.setGmtModified(LocalDateTime.now());
            stepMapper.insert(sysApprovalStep);

            // 获取当前审批步骤的审批条件
            SysApprovalSettingCondition settingCondition = settingConditionMapper.selectOne(Wrappers.<SysApprovalSettingCondition>lambdaQuery()
                    .eq(SysApprovalSettingCondition::getSettingId, setting.getId())
                    .eq(SysApprovalSettingCondition::getStepId, settingStep.getId())
                    .eq(SysApprovalSettingCondition::getIsDeleted, 0));
            Long conditionId = SnowflakeIdWorker.nextId();
            if (null != settingCondition) {
                // 新增业务审批步骤中的条件数据
                SysApprovalCondition sysApprovalCondition = EntityUtil.copy(settingCondition, SysApprovalCondition.class);
                sysApprovalCondition.setId(conditionId);
                sysApprovalCondition.setApprovalId(approvalId);
                sysApprovalCondition.setStepId(stepId);
                sysApprovalCondition.setCreateId(userId);
                sysApprovalCondition.setGmtCreate(LocalDateTime.now());
                sysApprovalCondition.setGmtModified(LocalDateTime.now());
                conditionMapper.insert(sysApprovalCondition);
            }
            // 根据当前步骤和条件获取审批人
            List<SysApprovalSettingMember> members = settingMemberMapper.selectList(Wrappers.<SysApprovalSettingMember>lambdaQuery()
                    .eq(SysApprovalSettingMember::getSettingId, setting.getId())
                    .eq(SysApprovalSettingMember::getStepId, settingStep.getId())
                    .eq(SysApprovalSettingMember::getIsDeleted, 0));
            Optional.ofNullable(members).orElse(new ArrayList<>()).forEach(member -> {
                SysApprovalMember sysApprovalMember = EntityUtil.copy(member, SysApprovalMember.class);
                sysApprovalMember.setId(SnowflakeIdWorker.nextId());
                sysApprovalMember.setApprovalId(approvalId);
                sysApprovalMember.setStepId(stepId);
                sysApprovalMember.setCreateId(userId);
                sysApprovalMember.setGmtCreate(LocalDateTime.now());
                sysApprovalMember.setGmtModified(LocalDateTime.now());
                if (member.getIsRelationCondition() == 1) {
                    sysApprovalMember.setConditionId(conditionId);
                    memberMapper.insert(sysApprovalMember);
                }
            });
        });
        /**
         * 获取步骤数组 end
         */
        SysApprovalProcess sysApprovalProcess = new SysApprovalProcess();
        sysApprovalProcess.setId(SnowflakeIdWorker.nextId());
        sysApprovalProcess.setApprovalId(sysApproval.getId());
        sysApprovalProcess.setStepId(1L);
        sysApprovalProcess.setStepName("创建订单");
        sysApprovalProcess.setUserId(userId);
        sysApprovalProcess.setUserName(userDTO.getFullName());
        sysApprovalProcess.setApprovalComments(ApprovalStatus.REVIEW_YES.getValue());
        sysApprovalProcess.setIsPass(1);
        sysApprovalProcess.setOperateResult(ApprovalStatus.REVIEW_YES.getCode());
        sysApprovalProcess.setCreateId(userId);
        sysApprovalProcess.setGmtCreate(LocalDateTime.now());
        sysApprovalProcess.setModifiedId(userId);
        sysApprovalProcess.setGmtModified(LocalDateTime.now());
        processMapper.insert(sysApprovalProcess);
        // 新增业务审批主表数据
        int insert = approvalMapper.insert(sysApproval);
        if (insert > 0) {
            try {
                // 如果这个审批有步骤才需要发邮件（产品说没有配置步骤好像就直接审批通过了。。。）
                if (settingSteps != null && settingSteps.size() > 0) {
                    log.info(sysApproval.getId() + "审批发送邮件。。。");
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            //发起了一个审批实例 邮件
                            //查询第一个步骤的审批人或审批部门
                            List<SysApprovalSettingMember> sasms = settingMemberMapper.selectList(Wrappers.<SysApprovalSettingMember>lambdaQuery()
                                    .eq(SysApprovalSettingMember::getSettingId, setting.getId())
                                    //                        .eq(SysApprovalSettingMember::getApproverId, approvalId)
                                    .eq(SysApprovalSettingMember::getStepId, settingSteps.get(0).getId())
                                    .eq(SysApprovalSettingMember::getIsDeleted, IsDeletedCode.NO.getCode()));
                            //要往这些用户上发邮件
                            Set<Long> userIds = new HashSet<>();
                            sasms.forEach(e -> {
                                if (ApproverType.DEPT.getCode().equals(e.getApproverType())) {
                                    List<Long> longs = sysDepartmentService.queryCUserIdsByDeptIdEffective(e.getApproverId());
                                    if (longs != null && longs.size() > 0) {
                                        userIds.addAll(longs);
                                    }
                                } else {
                                    userIds.add(e.getApproverId());
                                }
                            });
                            List<UserDTO> users = sysUserService.getUsers(userIds);
                            users.forEach(e -> {
                                String name = e.getCnSurname() + e.getCnName();
                                String title = "香港中旅社雲平臺审批通知";
                                String centent = getTemplate(name, title, setting.getBusinessTypeName(), setting.getApprovalTypeName());
                                try {
                                    mailTemplate.sendHtmlMail(e.getEmail(), title, centent);
                                } catch (MessagingException me2) {
                                    log.error("发送审批通知邮件错误，错误的信息：" + me2.getMessage());
                                }
                            });
                        }
                    }).start();
                }
            } catch (Exception e) {
                log.error("审批发送邮件失败：" + e.getMessage());
            }
        }
        ApprovalStartDTO dto = new ApprovalStartDTO();
        dto.setApprovalId(approvalId);
        return Result.success(dto);
    }

    /**
     * 生成审批编号，规则：spd+年月日時分秒+4位隨機数字
     * SPD2104281924020001
     *
     * @param userDTO
     * @return
     */
    private String generatorApprovalNumber(UserDTO userDTO) {
        StringBuffer numberSb = new StringBuffer("");
        String randomNumber = String.valueOf((int) ((Math.random() * 9 + 1) * 1000));
        numberSb.append("SPD").append(userDTO.getEmployeeNumber()).append(randomNumber);
        String approvalNumber = numberSb.toString().toUpperCase();
        return approvalNumber;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<ApprovalStartDTO> start(long businessTypeId, long approvalTypeId, long businessId, long userId, BigDecimal amount, String extendParams, List<Long> approverIds) {
        if (CollUtil.isEmpty(approverIds)) {
            return Result.failed(SystemError.WORKFLOW_APPROVAL_7011);
        }
        UserDTO userDTO = sysUserService.queryCacheUser(userId);
        List<Long> deptIds = new ArrayList<>();
        deptIds.add(userId);
        deptIds.addAll(sysDepartmentService.queryIdsByUserId(userId));
        SysApprovalSetting setting = settingMapper.getSettingByType(businessTypeId, approvalTypeId, deptIds);
        if (setting == null) {
            return Result.failed(SystemError.WORKFLOW_APPROVAL_7001);
        }

        AtomicLong currentStepId = new AtomicLong(0L);
        AtomicLong nextStepId = new AtomicLong(0L);

        SysApproval sysApproval = new SysApproval();
        Long approvalId = SnowflakeIdWorker.nextId();
        sysApproval.setId(approvalId);
        sysApproval.setStatus(ApprovalStatus.REVIEWING.getCode());
//        sysApproval.setApprovalNumber(setting.getSysCode());
        sysApproval.setApprovalNumber(generatorApprovalNumber(userDTO));
        sysApproval.setSettingId(setting.getId());
        sysApproval.setSponsorId(userId);
        sysApproval.setSponsorName(userDTO.getFullName());
        sysApproval.setDepartmentId(userDTO.getDeptId());
        sysApproval.setDepartmentName(userDTO.getDept());
        sysApproval.setBusinessType(businessTypeId);
        sysApproval.setBusinessId(businessId);
        sysApproval.setAmount(amount);
        sysApproval.setExtendParams(extendParams);
        sysApproval.setCreateId(userId);
        sysApproval.setGmtCreate(LocalDateTime.now());
        sysApproval.setGmtModified(null);

        /**
         * 获取步骤数组 遍历插入业务审批相关表中 start
         */
        int i = 0;
        List<SysApprovalSettingStep> settingSteps = settingStepMapper.selectList(Wrappers.<SysApprovalSettingStep>lambdaQuery()
                .eq(SysApprovalSettingStep::getSettingId, setting.getId())
                .eq(SysApprovalSettingStep::getIsDeleted, 0));
        if (CollUtil.isNotEmpty(settingSteps)) {
            for (SysApprovalSettingStep settingStep : settingSteps) {
                // 新增业务审批步骤数据
                SysApprovalStep sysApprovalStep = EntityUtil.copy(settingStep, SysApprovalStep.class);
                Long stepId = SnowflakeIdWorker.nextId();
                if (sysApprovalStep.getStep() == 1) {
                    sysApproval.setCurrentStepId(stepId);
                } else if (sysApprovalStep.getStep() == 2) {
                    sysApproval.setNextStepId(stepId);
                }

                sysApprovalStep.setId(stepId);
                sysApprovalStep.setApprovalId(approvalId);
                sysApprovalStep.setCreateId(userId);
                sysApprovalStep.setGmtCreate(LocalDateTime.now());
                sysApprovalStep.setGmtModified(null);
                stepMapper.insert(sysApprovalStep);

                // 获取当前审批步骤的审批条件
                SysApprovalSettingCondition settingCondition = settingConditionMapper.selectOne(Wrappers.<SysApprovalSettingCondition>lambdaQuery()
                        .eq(SysApprovalSettingCondition::getSettingId, setting.getId())
                        .eq(SysApprovalSettingCondition::getStepId, settingStep.getId())
                        .eq(SysApprovalSettingCondition::getIsDeleted, 0));
                // 新增业务审批步骤中的条件数据
                SysApprovalCondition sysApprovalCondition = EntityUtil.copy(settingCondition, SysApprovalCondition.class);
                Long conditionId = SnowflakeIdWorker.nextId();
                sysApprovalCondition.setId(conditionId);
                sysApprovalCondition.setApprovalId(approvalId);
                sysApprovalCondition.setStepId(stepId);
                sysApprovalCondition.setCreateId(userId);
                sysApprovalCondition.setGmtCreate(LocalDateTime.now());
                sysApprovalCondition.setGmtModified(null);
                conditionMapper.insert(sysApprovalCondition);
                // 如果此步骤是动态审批人则将审批人id修改成对应的id
                if (settingStep.getIsDynamic()) {
                    Long approverId = approverIds.get(i);
                    UserDTO userDto = sysUserService.queryCacheUser(userId);
                    SysApprovalMember sysApprovalMember = new SysApprovalMember();
                    sysApprovalMember.setId(SnowflakeIdWorker.nextId());
                    sysApprovalMember.setApprovalId(approvalId);
                    sysApprovalMember.setStepId(stepId);
                    sysApprovalMember.setIsRelationCondition(0);
                    sysApprovalMember.setApproverType(2);
                    sysApprovalMember.setApproverId(approverId);
                    sysApprovalMember.setApproverName(userDto.getFullName());
                    sysApprovalMember.setCreateId(userId);
                    sysApprovalMember.setGmtCreate(LocalDateTime.now());
                    sysApprovalMember.setGmtModified(null);
                    memberMapper.insert(sysApprovalMember);
                    // 如果此审批有金额条件判断,则主审批人也动态设置
                    if (null != amount && !amount.equals(BigDecimal.ZERO)) {
                        SysApprovalMember sysApprovalMasterMember = new SysApprovalMember();
                        sysApprovalMasterMember.setId(SnowflakeIdWorker.nextId());
                        sysApprovalMasterMember.setApprovalId(approvalId);
                        sysApprovalMasterMember.setStepId(stepId);
                        sysApprovalMasterMember.setApproverType(2);
                        sysApprovalMasterMember.setApproverId(approverId);
                        sysApprovalMasterMember.setApproverName(userDto.getFullName());
                        sysApprovalMasterMember.setIsRelationCondition(1);
                        sysApprovalMasterMember.setConditionId(conditionId);
                        sysApprovalMasterMember.setCreateId(userId);
                        sysApprovalMasterMember.setGmtCreate(LocalDateTime.now());
                        sysApprovalMasterMember.setGmtModified(null);
                        memberMapper.insert(sysApprovalMember);
                    }
                    i++;
                } else {
                    // 根据当前步骤和条件获取审批人
                    List<SysApprovalSettingMember> members = settingMemberMapper.selectList(Wrappers.<SysApprovalSettingMember>lambdaQuery()
                            .eq(SysApprovalSettingMember::getSettingId, setting.getId())
                            .eq(SysApprovalSettingMember::getStepId, settingStep.getId())
                            .eq(SysApprovalSettingMember::getIsRelationCondition, 1)
                            .eq(SysApprovalSettingMember::getConditionId, settingCondition.getId())
                            .eq(SysApprovalSettingMember::getIsDeleted, 0));
                    Optional.ofNullable(members).orElse(new ArrayList<>()).forEach(member -> {
                        SysApprovalMember sysApprovalMember = EntityUtil.copy(member, SysApprovalMember.class);
                        sysApprovalMember.setId(SnowflakeIdWorker.nextId());
                        sysApprovalMember.setApprovalId(approvalId);
                        sysApprovalMember.setStepId(stepId);
                        sysApprovalMember.setCreateId(userId);
                        sysApprovalMember.setGmtCreate(LocalDateTime.now());
                        sysApprovalMember.setGmtModified(null);
                        if (member.getIsRelationCondition() == 1) {
                            sysApprovalMember.setConditionId(conditionId);
                            memberMapper.insert(sysApprovalMember);
                        }
                    });
                }
            }
        }
        /**
         * 获取步骤数组 end
         */
        SysApprovalProcess sysApprovalProcess = new SysApprovalProcess();
        sysApprovalProcess.setId(SnowflakeIdWorker.nextId());
        sysApprovalProcess.setApprovalId(sysApproval.getId());
        sysApprovalProcess.setStepId(1L);
        sysApprovalProcess.setStepName("创建订单");
        sysApprovalProcess.setUserId(userId);
        sysApprovalProcess.setUserName(userDTO.getFullName());
        sysApprovalProcess.setApprovalComments(ApprovalStatus.REVIEW_YES.getValue());
        sysApprovalProcess.setIsPass(1);
        sysApprovalProcess.setOperateResult(ApprovalStatus.REVIEW_YES.getCode());
        sysApprovalProcess.setCreateId(userId);
        sysApprovalProcess.setGmtCreate(LocalDateTime.now());
        sysApprovalProcess.setModifiedId(userId);
        sysApprovalProcess.setGmtModified(LocalDateTime.now());
        processMapper.insert(sysApprovalProcess);
        // 新增业务审批主表数据
        approvalMapper.insert(sysApproval);

        ApprovalStartDTO dto = new ApprovalStartDTO();
        dto.setApprovalId(approvalId);
        return Result.success(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<ApprovalCheckDTO> check(long approvalId, long userId, int status, String comments) {
        // 获取当前用户所在部门id(包含上级),再将当前用户id放入list中
        List<Long> deptIds = sysDepartmentService.queryIdsByUserId(userId);
        deptIds.add(userId);
        String approverId = StringUtils.join(deptIds.toArray(), ",");
        ApprovalInfoDTO dto = approvalMapper.selectById(approvalId, userId);

        ApprovalCheckDTO result = new ApprovalCheckDTO();

        if (dto == null) {
            throw new BusinessException(SystemError.SYS_411);
        }
        List<Long> approverIdList = memberMapper.selectObjs(Wrappers.<SysApprovalMember>lambdaQuery()
                .select(SysApprovalMember::getApproverId).eq(SysApprovalMember::getStepId, dto.getCurrentStepId()))
                .stream().map(o -> (Long) o).collect(Collectors.toList());
        boolean flag = false;
        if (CollUtil.isNotEmpty(approverIdList)) {
            Set<Long> collect = deptIds.stream().distinct().filter(approverIdList::contains).collect(Collectors.toSet());
            if (CollectionUtils.isNotEmpty(collect)) flag = true;
        }
        dto.setIsApproverMe(flag);

        if (status == ApprovalStatus.RECALL.getCode()) {
            if (!dto.getIsMe()) {
                return Result.failed(SystemError.WORKFLOW_APPROVAL_7008);
            }
            // 撤回审批操作,当前状态必须是审批中
            if (dto.getStatus() != ApprovalStatus.REVIEWING.getCode()) {
                return Result.failed(SystemError.WORKFLOW_APPROVAL_7007);
            }
            // 获取此审批的当前步骤必须为第一步才可以撤回
            SysApprovalStep sysApprovalStep = stepMapper.selectOne(new QueryWrapper<SysApprovalStep>().lambda()
                    .eq(SysApprovalStep::getId, dto.getCurrentStepId())
                    .eq(SysApprovalStep::getIsDeleted, IsDeletedCode.NO.getCode())
                    .select(SysApprovalStep::getId, SysApprovalStep::getStep));
            if (sysApprovalStep == null && sysApprovalStep.getStep() != 1) {
                return Result.failed(SystemError.WORKFLOW_APPROVAL_7003);
            }
            // 修改审批状态为撤回状态
            SysApproval sysApproval = new SysApproval();
            sysApproval.setId(approvalId);
            sysApproval.setStatus(status);
            approvalMapper.updateById(sysApproval);

            // 如果是撤回操作则直接算是审批走完的状态
            result.setIsFinish(true);
        } else {
            if (!dto.getIsApproverMe()) {
                return Result.failed(SystemError.WORKFLOW_APPROVAL_7009);
            }
            if (dto.getIsApproval()) {
                return Result.failed(SystemError.WORKFLOW_APPROVAL_7010);
            }
            if (status == ApprovalStatus.REVIEW_NO.getCode()) {
                if (StringUtils.isBlank(comments)) {
                    // 审批拒绝必须填写理由
                    return Result.failed(SystemError.WORKFLOW_APPROVAL_7006);
                }
            }

            // 获取此审批的当前步骤
            SysApprovalStep sysApprovalStep = stepMapper.selectById(dto.getCurrentStepId());
            if (sysApprovalStep == null || sysApprovalStep.getIsDeleted() == 1) {
                return Result.failed(SystemError.WORKFLOW_APPROVAL_7003);
            }
            // 获取当前步骤的所有审批人
            List<SysApprovalMember> sysApprovalMembers = memberMapper.selectList(Wrappers.<SysApprovalMember>lambdaQuery()
                    .eq(SysApprovalMember::getApprovalId, dto.getId())
                    .eq(SysApprovalMember::getStepId, sysApprovalStep.getId())
                    .eq(SysApprovalMember::getIsDeleted, 0));
            if (CollUtil.isEmpty(sysApprovalMembers)) {
                return Result.failed(SystemError.WORKFLOW_APPROVAL_7004);
            }
            /*boolean isMember = sysApprovalMembers.stream().filter(member->member.getUserId() == userId).findAny().isPresent();
            // 判断当前用户是否存在当前步骤审批人中
            if (!isMember) {
                return Result.failed(SystemError.WORKFLOW_APPROVAL_7005);
            }*/

            List<Long> approverIds = sysApprovalMembers.stream().map(SysApprovalMember::getApproverId).collect(Collectors.toList());
            // 判断是否存在审批金额,存在则会有主审批人与副审批人,根据条件选择正确审批人
            SysApprovalCondition sysApprovalCondition = conditionMapper.selectOne(Wrappers.<SysApprovalCondition>lambdaQuery()
                    .eq(SysApprovalCondition::getApprovalId, approvalId)
                    .eq(SysApprovalCondition::getStepId, sysApprovalStep.getId())
                    .eq(SysApprovalCondition::getIsDeleted, 0)
            );
            if (null != sysApprovalCondition) {
                // 符合条件则使用主审批人,amount大于等于valueBegin并且小于等于valueEnd
                if (dto.getAmount().compareTo(sysApprovalCondition.getValueBegin()) > -1 && dto.getAmount().compareTo(sysApprovalCondition.getValueEnd()) < 1) {
                    approverIds = sysApprovalMembers.stream().filter(member -> member.getConditionId().equals(sysApprovalCondition.getId())).map(SysApprovalMember::getApproverId).collect(Collectors.toList());
                } else {
                    // 不符合条件获取副审批人
                    approverIds = sysApprovalMembers.stream().filter(member -> member.getIsRelationCondition() == 0).map(SysApprovalMember::getApproverId).collect(Collectors.toList());
                }
            }

            List<Long> intersection = approverIds.stream().filter(deptIds::contains).collect(Collectors.toList());
            // 最后判断当前用户是否在此次流程审批人当中
            if (CollUtil.isEmpty(intersection)) {
                return Result.failed(SystemError.WORKFLOW_APPROVAL_7009);
            }

            QueryWrapper<SysApprovalStep> qw = new QueryWrapper<>();
            qw.lambda().eq(SysApprovalStep::getApprovalId, approvalId)
                    .gt(SysApprovalStep::getStep, sysApprovalStep.getStep())
                    .eq(SysApprovalStep::getIsDeleted, 0)
                    .orderByAsc(SysApprovalStep::getStep);
            // 获取后面的审批步骤
            List<SysApprovalStep> approvalSteps = stepMapper.selectList(qw);

            // 不存在后面的审批则表示整个审批流程已走完
            boolean isFinish = CollUtil.isEmpty(approvalSteps) ? true : false;
            //流程没有走完 给下一个步骤的审批人发邮件
            if (!isFinish) {
                try {
                    log.info(approvalId + "审批给下一步操作人发送邮件。。。");
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            SysApproval sysApproval = approvalMapper.selectById(approvalId);
                            if (sysApproval != null) {
                                SysApprovalSetting setting = settingMapper.selectById(sysApproval.getSettingId());
                                if (setting != null) {
                                    //查询第一个步骤的审批人或审批部门
                                    List<SysApprovalSettingMember> sasms = settingMemberMapper.selectList(Wrappers.<SysApprovalSettingMember>lambdaQuery()
                                            .eq(SysApprovalSettingMember::getApproverId, approvalId)
                                            .eq(SysApprovalSettingMember::getStepId, approvalSteps.get(0).getId())
                                            .eq(SysApprovalSettingMember::getIsDeleted, IsDeletedCode.NO.getCode()));
                                    //要往这些用户上发邮件
                                    Set<Long> userIds = new HashSet<>();
                                    sasms.forEach(e -> {
                                        if (ApproverType.DEPT.getCode().equals(e.getApproverType())) {
                                            List<Long> longs = sysDepartmentService.queryCUserIdsByDeptIdEffective(e.getApproverId());
                                            if (longs != null && longs.size() > 0) {
                                                userIds.addAll(longs);
                                            }
                                        } else {
                                            userIds.add(e.getApproverId());
                                        }
                                    });
                                    List<UserDTO> users = sysUserService.getUsers(userIds);
                                    users.forEach(e -> {
                                        String name = e.getCnSurname() + e.getCnName();
                                        String title = "香港中旅社雲平臺审批通知";
                                        String centent = getTemplate(name, title, setting.getBusinessTypeName(), setting.getApprovalTypeName());
                                        try {
                                            mailTemplate.sendHtmlMail(e.getEmail(), title, centent);
                                        } catch (MessagingException me2) {
                                            log.error("发送审批通知邮件错误，错误的信息：" + me2.getMessage());
                                        }
                                    });
                                }
                            }
                        }
                    }).start();
                } catch (Exception e) {
                    log.error("审批发送邮件失败：" + e.getMessage());
                }
            }
            // 修改审批状态
            SysApproval sysApproval = new SysApproval();
            sysApproval.setId(approvalId);
            // 如果是审批不通过操作,可直接更改状态
            int approvalStatus = dto.getStatus();
            if (status == ApprovalStatus.REVIEW_NO.getCode()) {
                approvalStatus = status;
            } else {
                // 如果是审批通过操作,需要校验只有走完了整个审批流程才会更改审批主状态
                approvalStatus = isFinish ? status : dto.getStatus();
            }
            sysApproval.setStatus(approvalStatus);
            // size>0时表示还有多个步骤流程,获取下一步id置为当前步骤id,否则currentStepId不变
            sysApproval.setCurrentStepId(!isFinish && approvalSteps.size() > 0 ? approvalSteps.get(0).getId() : dto.getCurrentStepId());
            // 将当前步骤id赋值给上一步id,如果审批流程已走完则lastStepId不变
            sysApproval.setLastStepId(!isFinish ? dto.getCurrentStepId() : dto.getLastStepId());
            // size>1时表示还有多个步骤流程,获取后面的第2步骤id为下一步步骤id,否则nextStepId置为null
            sysApproval.setNextStepId(!isFinish && approvalSteps.size() > 1 ? approvalSteps.get(1).getId() : null);
            approvalMapper.updateById(sysApproval);

            // 设置当前步骤状态为已审批(通过/不通过都属于已审批)
            SysApprovalStep approvalStep = new SysApprovalStep();
            approvalStep.setId(dto.getCurrentStepId());
            approvalStep.setIsApproval(1);
            stepMapper.updateById(approvalStep);

            // 审批流水操作
            SysApprovalProcess sysApprovalProcess = new SysApprovalProcess();
            sysApprovalProcess.setApprovalId(approvalId);
            sysApprovalProcess.setStepId(dto.getCurrentStepId());
            sysApprovalProcess.setStepName(sysApprovalStep.getStepName());
            sysApprovalProcess.setUserId(userId);
            sysApprovalProcess.setUserName(sysUserService.loadUserByParam(userId, 1).getFullName());
            sysApprovalProcess.setIsPass(status == ApprovalStatus.REVIEW_YES.getCode() ? 1 : 0);
            sysApprovalProcess.setApprovalComments(comments);
            sysApprovalProcess.setOperateResult(status);
            sysApprovalProcess.setCreateId(userId);
            sysApprovalProcess.setGmtCreate(LocalDateTime.now());
            sysApprovalProcess.setModifiedId(userId);
            sysApprovalProcess.setGmtModified(LocalDateTime.now());
            processMapper.insert(sysApprovalProcess);

            result.setIsFinish(isFinish);
        }

        return Result.success(result);
    }

    @Override
    public PageResponse<ApprovalDTO> queryPage(ApprovalReq req, long userId) {
        IPage<ApprovalDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        IPage<ApprovalDTO> approvalPage = new Page<>();
        log.info("【审批-查询列表】审批列表分页查询请求:{}", JSON.toJSON(req));
        // 获取当前用户所在部门id(包含上级),再将当前用户id放入list中
        List<Long> deptIds = sysDepartmentService.queryIdsByUserId(userId);
        deptIds.add(userId);
        String approverId = StringUtils.join(deptIds.toArray(), ",");
        req.setSponsorId(approverId);
        if (req.getType() == 1) {
            approvalPage = approvalMapper.selectListPage(iPage, req);
        } else {
            approvalPage = approvalMapper.selectListPageMyApproval(iPage, req);
        }
        log.info("【审批-查询列表】查询审批列表结果:{}", JSON.toJSON(approvalPage));
        if (CollectionUtils.isEmpty(approvalPage.getRecords())) {
            return PageResponse.empty(approvalPage.getCurrent());
        }
        approvalPage.getRecords().forEach(approvalDTO -> {
            UserDTO userDTO = sysUserService.queryCacheUser(userId);
            System.out.println("【审批-查询列表】查询审批类型:" + JSON.toJSONString(userDTO) + ",approvalDTO:" + JSON.toJSONString(approvalDTO));
            if (null != userDTO) {
                approvalDTO.setDepartmentId(userDTO.getDeptId());
                approvalDTO.setDepartmentName(userDTO.getDept());
            }

            approvalDTO.setApprovalTypeName(SysApprovalType.parseValue(approvalDTO.getApprovalType()));
        });
        PageResponse<ApprovalDTO> result = new PageResponse<>(
                approvalPage.getRecords(),
                approvalPage.getCurrent() == 1,
                approvalPage.getTotal() <= (approvalPage.getCurrent() * approvalPage.getSize()),
                approvalPage.getTotal(),
                approvalPage.getCurrent(),
                approvalPage.getSize());
        return result;
    }

    @Override
    public ApprovalInfoDTO query(long id, long userId) {
        // 获取当前用户所在部门id(包含上级),再将当前用户id放入list中
        List<Long> deptIds = sysDepartmentService.queryIdsByUserId(userId);
        deptIds.add(userId);
        String approverId = StringUtils.join(deptIds.toArray(), ",");
        ApprovalInfoDTO dto = approvalMapper.selectById(id, userId);
        // 查询当前节点的审批人列表
        List<Long> approverIdList = memberMapper.selectObjs(Wrappers.<SysApprovalMember>lambdaQuery()
                .select(SysApprovalMember::getApproverId)
                .eq(SysApprovalMember::getStepId, dto.getCurrentStepId())).stream().map(o -> (Long) o).collect(Collectors.toList());
        // approverIdList包含在其中就可以审批
        log.info("【审批服务-查询审批信息】审批人ID对比, sysUserIds:{}, approvalUserIds:{}", JSON.toJSONString(deptIds), JSON.toJSONString(approverIdList));
        boolean flag = false;
        if (CollUtil.isNotEmpty(approverIdList)) {
            Set<Long> collect = deptIds.stream().distinct().filter(approverIdList::contains).collect(Collectors.toSet());
            if (CollectionUtils.isNotEmpty(collect)) flag = true;
        }
        dto.setIsApproverMe(flag);

        List<SysApprovalProcess> SysProcesses = processMapper.selectList(Wrappers.<SysApprovalProcess>lambdaQuery()
                .eq(SysApprovalProcess::getApprovalId, id)
                .orderByDesc(SysApprovalProcess::getGmtCreate)
        );
        List<ApprovalProcessDTO> processes = EntityUtil.copyList(SysProcesses, ApprovalProcessDTO.class);
        dto.setProcesses(processes);
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approval(long id, int status, long userId, String comments) {
        // 获取当前用户所在部门id(包含上级),再将当前用户id放入list中
        List<Long> deptIds = sysDepartmentService.queryIdsByUserId(userId);
        deptIds.add(userId);
        String approverId = StringUtils.join(deptIds.toArray(), ",");
        ApprovalInfoDTO dto = approvalMapper.selectById(id, userId);
        if (dto == null) {
            throw new BusinessException(SystemError.SYS_411);
        }

        List<Long> approverIdList = memberMapper.selectObjs(Wrappers.<SysApprovalMember>lambdaQuery().select(SysApprovalMember::getApproverId).eq(SysApprovalMember::getStepId, dto.getCurrentStepId())).stream().map(o -> (Long) o).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(approverIdList) && Collections.disjoint(approverIdList, deptIds)) {
            dto.setIsApproverMe(true);
        } else {
            dto.setIsApproverMe(false);
        }

        if (status == ApprovalStatus.RECALL.getCode()) {
            if (!dto.getIsMe()) {
                throw new BusinessException(SystemError.WORKFLOW_APPROVAL_7008);
            }
            // 撤回审批操作,当前状态必须是待审批才可以撤回
            if (dto.getStatus() != 1) {
                throw new BusinessException(SystemError.WORKFLOW_APPROVAL_7007);
            }

            // 修改审批状态为撤回状态
            SysApproval sysApproval = new SysApproval();
            sysApproval.setId(id);
            sysApproval.setStatus(status);
            approvalMapper.updateById(sysApproval);

        } else {
            if (!dto.getIsApproverMe()) {
                throw new BusinessException(SystemError.WORKFLOW_APPROVAL_7009);
            }
            if (dto.getIsApproval()) {
                throw new BusinessException(SystemError.WORKFLOW_APPROVAL_7010);
            }

            SysApprovalStep sysApprovalStep = stepMapper.selectById(dto.getCurrentStepId());
            if (sysApprovalStep == null || sysApprovalStep.getIsDeleted() == 1) {
                throw new BusinessException(SystemError.WORKFLOW_APPROVAL_7003);
            }
            // 获取后面的审批步骤
            List<SysApprovalStep> approvalSteps = stepMapper.selectList(Wrappers.<SysApprovalStep>lambdaQuery()
                    .eq(SysApprovalStep::getApprovalId, id)
                    .gt(SysApprovalStep::getStep, sysApprovalStep.getStep())
                    .eq(SysApprovalStep::getIsDeleted, 0)
            );

            // 不存在后面的审批则表示整个审批流程已走完
            boolean isFinish = CollUtil.isEmpty(approvalSteps) ? true : false;

            // 修改审批状态
            SysApproval sysApproval = new SysApproval();
            sysApproval.setId(id);
            // 如果是审批不通过操作,可直接更改状态
            int approvalStatus = dto.getStatus();
            if (status == ApprovalStatus.REVIEW_NO.getCode()) {
                approvalStatus = status;
            } else {
                // 如果是审批通过操作,需要校验只有走完了整个审批流程才会更改审批主状态
                approvalStatus = isFinish ? status : dto.getStatus();
            }
            sysApproval.setStatus(approvalStatus);
            // size>0时表示还有多个步骤流程,获取下一步id置为当前步骤id,否则currentStepId不变
            sysApproval.setCurrentStepId(!isFinish && approvalSteps.size() > 0 ? approvalSteps.get(0).getId() : dto.getCurrentStepId());
            // 将当前步骤id赋值给上一步id,如果审批流程已走完则lastStepId不变
            sysApproval.setLastStepId(!isFinish ? dto.getCurrentStepId() : dto.getLastStepId());
            // size>1时表示还有多个步骤流程,获取后面的第2步骤id为下一步步骤id,否则nextStepId置为null
            sysApproval.setNextStepId(!isFinish && approvalSteps.size() > 1 ? approvalSteps.get(1).getId() : null);
            approvalMapper.updateById(sysApproval);

            // 设置当前步骤状态为已审批(通过/不通过都属于已审批)
            SysApprovalStep approvalStep = new SysApprovalStep();
            approvalStep.setId(dto.getCurrentStepId());
            approvalStep.setIsApproval(1);
            stepMapper.updateById(approvalStep);

            // 审批流水操作
            SysApprovalProcess sysApprovalProcess = new SysApprovalProcess();
            sysApprovalProcess.setApprovalId(id);
            sysApprovalProcess.setStepId(dto.getCurrentStepId());
            sysApprovalProcess.setStepName(approvalStep.getStepName());
            sysApprovalProcess.setUserId(userId);
            sysApprovalProcess.setUserName(sysUserService.loadUserByParam(userId, 1).getFullName());
            sysApprovalProcess.setIsPass(status == ApprovalStatus.REVIEW_YES.getCode() ? 1 : 0);
            sysApprovalProcess.setApprovalComments(comments);
            sysApprovalProcess.setOperateResult(1);
            processMapper.insert(sysApprovalProcess);
        }

    }

    @Override
    public List<BusinessTypeEnumDTO> queryEnum() {
        return queryEnums();
    }


    private static List<BusinessTypeEnumDTO> queryEnums() {
        List<BusinessTypeEnumDTO> businessDtos = new ArrayList<>();
        ApprovalBusinessMapper[] approvalBusinessMappers = ApprovalBusinessMapper.values();
        SystemBusinessType[] values = SystemBusinessType.values();
        for (SystemBusinessType businessType : values) {
            BusinessTypeEnumDTO businessTypeEnumDTO = new BusinessTypeEnumDTO();
            businessDtos.add(businessTypeEnumDTO);
            businessTypeEnumDTO.setId(businessType.getCode());
            businessTypeEnumDTO.setName(businessType.getValue());
            List<ApprovalTypeEnumDTO> approvalEnumDTOS = new ArrayList<>();
            businessTypeEnumDTO.setApprovalTypes(approvalEnumDTOS);
            // 构建审批类型
            for (ApprovalBusinessMapper appBusMapper : approvalBusinessMappers) {
                if (appBusMapper.getBusinessTypeList().contains(businessType)) {
                    ApprovalTypeEnumDTO approvalTypeEnumDTO = new ApprovalTypeEnumDTO();
                    approvalEnumDTOS.add(approvalTypeEnumDTO);
                    String appCode = StringUtils.leftPad(String.valueOf(appBusMapper.getCode()), 2, "0");
                    String busCode = StringUtils.leftPad(String.valueOf(businessType.getCode()), 2, "0");
                    String id = busCode.concat(appCode);
                    approvalTypeEnumDTO.setId(Integer.valueOf(id));
                    approvalTypeEnumDTO.setName(String.format("%s(%s)", appBusMapper.getValue(), businessType.getValue()));
                    approvalTypeEnumDTO.setIsCondition(appBusMapper.isCondition());
                    //            System.out.println("code:" + code + ",business type:" + businessType.getValue() + ",approval type:" + appBusMapper.getValue() + ",is condition:" + appBusMapper.isCondition());
//                    System.out.println("{ value:" + Integer.valueOf(code) + ", text: '" + appBusMapper.getValue().trim() + "("+businessType.getValue()+")'},");//前端
//                    System.out.println(code+"("+Integer.valueOf(code) + ",\"" + appBusMapper.getValue().trim() + "("+businessType.getValue()+")\"),");//后台
                }
            }
        }
        businessDtos.sort((o1, o2) -> {
            Integer x = o1.getId();
            Integer y = o2.getId();
            return x.compareTo(y);
        });
        for (BusinessTypeEnumDTO businessDto : businessDtos) {
            for (ApprovalTypeEnumDTO approvalType : businessDto.getApprovalTypes()) {
                Integer code = approvalType.getId();
//                System.out.println("{ value:" + Integer.valueOf(code) + ", text: '" + approvalType.getName() + "(" + businessDto.getName() + ")'},");//前端
                System.out.println(code + "(" + code + ",\"" + approvalType.getName() + "\"," + approvalType.getIsCondition() + "),");//后台
            }
        }
        return businessDtos;
    }

    /**
     * 获取模板
     *
     * @param name         用户中文名称
     * @param title        标题
     * @param businessType 相关类型
     * @param typeName     相关类型描述
     * @return
     */
    private String getTemplate(String name, String title, String businessType, String typeName) {
        StringBuffer sb = new StringBuffer();
        sb.append("<!DOCTYPE HTML>\n");
        sb.append("<html lang=\"en-US\">\n");
        sb.append("<head>\n");
        sb.append("\t<meta charset=\"UTF-8\">\n");
        sb.append("\t<title>" + title + "</title>\n");
        sb.append("\t<style type=\"text/css\">\n");
        sb.append("\t\t.template{\n");
        sb.append("\t\t\twidth: 800px;\n");
        sb.append("\t\t\tmargin: 50px auto 0px auto;\n");
        sb.append("\t\t}\n");
        sb.append("\t\tp,a{\n");
        sb.append("\t\t\tpadding-left:2em;\n");
        sb.append("\t\t}\n");
        sb.append("\t</style>\n");
        sb.append("</head>\n");
        sb.append("<body>\n");
        sb.append("\t<div class=\"template\" >\n");
        sb.append("\t\t<h3>亲爱的 <span>" + name + "</span>：</h3>\n");
//        sb.append("\t\t<p>您收到一条新的待办通知</p>\n");
        sb.append("\t\t<p>来自" + businessType + "的通知，您有一条-" + typeName + "-的审批提醒，请及时处理。</p>\n");
//        sb.append("\t\t<br/>\n");
//        sb.append("\t\t<p>You have a new to-do list to deal with.</p>\n");
//        sb.append("\t\t<p>You have received a new notification.</p>\n");
        sb.append("\t</div>\n");
        sb.append("</body>\n");
        sb.append("</html>");
        return sb.toString();
    }
}
